#ifndef LOGINLOGICAL_H
#define LOGINLOGICAL_H

#include <QObject>
#include <QThread>
#include <QImage>

#include "src/authenticate/acctauthenticate.h"
//#include "src/authenticate/faceauthinterface.h"
#include "src/authenticate/faceauthenticate_cv.h"

#ifdef USE_OPENCV
#include <opencv2/opencv.hpp>
#else
#include <QCamera>
#include <QCameraImageCapture>
#endif


class Loginlogical : public QThread
{
    Q_OBJECT
public:
    enum Login_Auth_Type
    {
        Login_Auth_Account,
        Login_Auth_FaceRegist,
        Login_Auth_Face,
        Login_Auth_Voice,
        Login_Auth_Finger,
        Login_Auth_Eye
    };

    enum Login_Result
    {
        Login_Success = 0,
        Login_Failed_AcctpwdError = 1,
        Login_Failed_Locked = 2,
        Login_Failed_Faceunknown,
    };

    enum Face_Regist_Result
    {
        Face_Regist_Success = 0,
        Face_Regist_Failed_Timeout,
        Face_Regist_Failed_Nocamera,
        Face_Regist_Failed_Canceled

    };

    enum Face_Predict_Result
    {
        Face_Predict_Success = 0,
        Face_Predict_Failed_Nocamera,
        Face_Predict_Failed_Noface,
        Face_Predict_Failed_Timeout,
        Face_Predict_Failed_Unknownface
    };

public:
    explicit Loginlogical(QObject *parent = nullptr);
    ~Loginlogical();

    quint32 getCanRetryCount();
    quint32 getLockRetryTimedelay();

    static QString getSecondsString(quint32 seconds);
    static QString getSystemUsername();

    void loginThread(const QString& uname, const QString&passwd);

    void faceRegistThread(int cameraIndex); //const QString& camera);

    void facePredictThread(int cameraIndex); //const QString& camera);



#ifdef USE_OPENCV
    void removeFaceLabel(const QString& label);
    bool editFaceLabel(const QString& label, const QString& newLabel);
    QList<QString> getRegistedFaceLabels() {return m_faceAPI->getLabels();}
    void stopThreadCapturing();
    static QImage matToQImage(const cv::Mat& mat);
    bool isThreadCapturing() {return (m_cap!=nullptr && m_cap->isOpened()) || m_play;}
#else
    void stopThreadCapturing() {if (curCamera) {curCamera->stop();}}
    bool isThreadCapturing() {return curCamera==nullptr ? false : (curCamera->state() == QCamera::ActiveState);}
#endif


public slots:
    void onFaceregistImageCaptured(int id, const QImage & image);

signals:
    void sigLoginResult(Loginlogical::Login_Result result, const QString& resultMsg);

    void sigFacePreviewImage(const QImage& image);

    void sigFaceRegistLongtimenoface();
    void sigFaceRegistProcessing(int step, int total);
    void sigFaceRegistResult(Loginlogical::Face_Regist_Result result, const QString& label);

    void sigFacePredictResult(Loginlogical::Face_Predict_Result result);

protected:
    void run() override;

private:
    Login_Result login(const QString& uname, const QString&passwd, QString& resultMsg);

private:
    Login_Auth_Type m_auth_type;

    AcctAuthenticate m_AuthModule;
    QString m_uname;
    QString m_passwd;

    FaceAuthenticateCV* m_faceAPI;
    QString m_cameraId;
    int m_cameraIndex;
    bool m_play = false;

#ifdef USE_OPENCV
    cv::VideoCapture* m_cap = nullptr;
    cv::Mat m_mat;

    Face_Regist_Result faceRegist(QString label);
    Face_Predict_Result facePredict();
    QString generateFaceLabel(const QList<QString>& existLables);
#else
    QCamera * curCamera = nullptr;
    QCameraImageCapture * imageCapture = nullptr;
#endif


};

#endif // LOGINLOGICAL_H
